package com.jishucai.rpc.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author admin
 */
public class RpcServer {
    // 通过一个map 保存所有的提供者
    private Map<String, Object> registerMap = new HashMap<>(8);

    // 用于缓存指定包中所有提供者的类名
    private List<String> classCache = new ArrayList<>();

    // 将指定包中的所有提供者进行发布（写入服务注册表）

    public void publish(String basePackage) throws Exception {

        getProviderClass(basePackage);

        doRegister();

    }

    private void getProviderClass(String basePackage) {
        // 获取指定包中的资源
        URL resource = this.getClass().getClassLoader().getResource(basePackage.replaceAll("\\.", "/"));

        if (resource == null) {
            return;
        }

        // 将Url资源转化为file
        File dir = new File(resource.getFile());

        // 遍历指定包中及其子孙包中所有的文件。
        for (File file : dir.listFiles()) {
            if (file.isDirectory()) {

                getProviderClass(basePackage + "." + file.getName());

            } else if (file.getName().endsWith(".class")) {

                String fileName = file.getName().replace(".class", "").trim();
                classCache.add(basePackage + "." + fileName);

            }
        }
    }

    private void doRegister() throws Exception {
        if (classCache.size() == 0) {
            return;
        }

        for (String className : classCache) {
            Class<?> clazz = Class.forName(className);
            registerMap.put(clazz.getInterfaces()[0].getName(), clazz.getDeclaredConstructor().newInstance());
        }
    }

    public void start() throws InterruptedException {
        NioEventLoopGroup parentGroup = new NioEventLoopGroup();
        NioEventLoopGroup childGroup = new NioEventLoopGroup();

        try {

            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(parentGroup, childGroup)
                    // 用于指定当服务端请求处理线程全部用完时，临时存放已经完成了三次握手的请求队列的长度
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    // 指定是否启用心跳机制来维护C/S间的长连接。
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    // 指定要创建的Channel的类型
                    .channel(NioServerSocketChannel.class)

                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            pipeline.addLast(new ObjectEncoder());
                            pipeline.addLast(new ObjectDecoder(Integer.MAX_VALUE,
                                    ClassResolvers.cacheDisabled(null)));

                            pipeline.addLast(new RpcServerHandler(registerMap));

                        }
                    });

            serverBootstrap.bind(8888).sync();

            System.out.println("Server已启动");

        } finally {
//            parentGroup.shutdownGracefully();
//            childGroup.shutdownGracefully();
        }
    }
}
